﻿using System;
using System.Windows;
using System.Windows.Input;
using System.Collections.Specialized;
using System.Collections.ObjectModel;
using InHD.commands;
using InHD.model;
using InHD.dataaccess;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Data;
using InHD.utilities;
using InHD.Properties;

namespace InHD.viewmodels
{
    public class MainViewModel : ViewModelBase
    {
        #region Fields
        readonly CompanyInfoRepository _companyInfoRepository;
        readonly TransactionRepository _transactionRepository;
        readonly RegisterPrintingRepository _registerPrintingRepository;
        #endregion

        #region Constructor

        public MainViewModel()
        {
            this._companyInfoRepository = new CompanyInfoRepository();
            this._companyInfoRepository.LoadCompanyInfo();
            this._transactionRepository = new TransactionRepository();
            this._registerPrintingRepository = new RegisterPrintingRepository();
        }

        public MainViewModel(Staff currentStaff)
        {
            this.CurrentStaff = currentStaff;
            this._companyInfoRepository = new CompanyInfoRepository();
            this._companyInfoRepository.LoadCompanyInfo();
            this._transactionRepository = new TransactionRepository();
            this._registerPrintingRepository = new RegisterPrintingRepository();
        }

        #endregion

        #region Event Handlers

        void Workspaces_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.NewItems)
                    workspace.RequestClose += this.OnWorkspaceRequestClose;

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.OldItems)
                    workspace.RequestClose -= this.OnWorkspaceRequestClose;
        }

        private void OnWorkspaceRequestClose(object sender, EventArgs e)
        {
            WorkspaceViewModel workspace = sender as WorkspaceViewModel;
            workspace.Dispose();
            this.Workspaces.Remove(workspace);
        }

        #endregion

        #region Commands

        private RelayCommand _exitCommand;
        public ICommand ExitCommand
        {
            get { return _exitCommand ?? (_exitCommand = new RelayCommand((param) => Application.Current.Shutdown())); }
        }

        private RelayCommand _newCompanyInfoCommand;
        public ICommand NewCompanyInfoCommand
        {
            get { return _newCompanyInfoCommand ?? (_newCompanyInfoCommand = new RelayCommand((param) => this.NewCompanyInfo())); }
        }

        private void NewCompanyInfo()
        {
            CompanyInfoViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is CompanyInfoViewModel)
                {
                    workspace = vm as CompanyInfoViewModel;
                }
            }

            if (workspace == null)
            {
                if (this._companyInfoRepository.CompanyInfoExist)
                {
                    workspace = new CompanyInfoViewModel(this._companyInfoRepository.CompanyInformation.CreateShallowCopy(), _companyInfoRepository);
                }
                else
                {
                    CompanyInfo newCompanyInfo = CompanyInfo.CreateNewCompanyInfo();
                    workspace = new CompanyInfoViewModel(newCompanyInfo, this._companyInfoRepository);
                }

                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _newTransactionCommand;
        public ICommand NewTransactionCommand
        {
            get { return _newTransactionCommand ?? (_newTransactionCommand = new RelayCommand((param) => this.NewTransaction())); }
        }

        private void NewTransaction()
        {
            TransactionViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is TransactionViewModel)
                {
                    workspace = vm as TransactionViewModel;
                }
            }

            if (workspace == null)
            {
                Transaction newTransaction = Transaction.CreateNewTransaction();
                workspace = new TransactionViewModel(newTransaction, this._transactionRepository);
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }
        
        private RelayCommand _newProductCommand;
        public ICommand NewProductCommand
        {
            get { return _newProductCommand ?? (_newProductCommand = new RelayCommand((param) => this.NewProduct())); }
        }

        private void NewProduct()
        {
            ProductViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is ProductViewModel)
                {
                    workspace = vm as ProductViewModel;
                }
            }

            if (workspace == null)
            {
                workspace = new ProductViewModel();
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _newCategoryCommand;
        public ICommand NewCategoryCommand
        {
            get { return _newCategoryCommand ?? (_newCategoryCommand = new RelayCommand((param) => this.NewCategory())); }
        }

        private void NewCategory()
        {
            CategoryViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is CategoryViewModel)
                {
                    workspace = vm as CategoryViewModel;
                }
            }

            if (workspace == null)
            {
                //Category newCategory = Category.CreateCategory();
                workspace = new CategoryViewModel();
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _manageSuppliersCommand;
        public ICommand ManageSuppliersCommand
        {
            get { return _manageSuppliersCommand ?? (_manageSuppliersCommand = new RelayCommand((param) => this.ManageSuppliers())); }
        }

        private void ManageSuppliers()
        {
            SupplierViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is SupplierViewModel)
                {
                    workspace = vm as SupplierViewModel;
                }
            }

            if (workspace == null)
            {
                //Category newCategory = Category.CreateCategory();
                workspace = new SupplierViewModel();
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _manageCustomersCommand;
        public ICommand ManageCustomersCommand
        {
            get { return _manageCustomersCommand ?? (_manageCustomersCommand = new RelayCommand((param) => this.ManageCustomers())); }
        }

        private void ManageCustomers()
        {
            CustomerViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is CustomerViewModel)
                {
                    workspace = vm as CustomerViewModel;
                }
            }

            if (workspace == null)
            {
                //Category newCategory = Category.CreateCategory();
                workspace = new CustomerViewModel();
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _manageStaffsCommand;
        public ICommand ManageStaffsCommand
        {
            get { return _manageStaffsCommand ?? (_manageStaffsCommand = new RelayCommand((param) => this.ManageStaffs())); }
        }

        private void ManageStaffs()
        {
            StaffViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is StaffViewModel)
                {
                    workspace = vm as StaffViewModel;
                }
            }

            if (workspace == null)
            {
                workspace = new StaffViewModel();
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _registerPrintingCommand;
        public ICommand RegisterPrintingCommand
        {
            get { return _registerPrintingCommand ?? (_registerPrintingCommand = new RelayCommand((param) => this.RegisterPrinting())); }
        }

        private void RegisterPrinting()
        {
            RegisterPrintingViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is RegisterPrintingViewModel)
                {
                    workspace = vm as RegisterPrintingViewModel;
                }
            }

            if (workspace == null)
            {
                RegisterPrinting newRegisterPrinting = InHD.model.RegisterPrinting.CreateNewRegisterPrinting();
                workspace = new RegisterPrintingViewModel(newRegisterPrinting, _registerPrintingRepository, this._companyInfoRepository.GetCompanyInfos()[0]);
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _receiveGoodsCommand;
        public ICommand ReceiveGoodsCommand
        {
            get { return _receiveGoodsCommand ?? (_receiveGoodsCommand = new RelayCommand((param) => this.ReceiveGoods())); }
        }

        private void ReceiveGoods()
        {
            ReceiveGoodsViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is ReceiveGoodsViewModel)
                {
                    workspace = vm as ReceiveGoodsViewModel;
                }
            }

            if (workspace == null)
            {
                workspace = new ReceiveGoodsViewModel();
                workspace.StaffUNK = this.CurrentStaff.StaffUNK;
                this.Workspaces.Add(workspace);
            }
            
            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _saleCommand;
        public ICommand SaleCommand
        {
            get { return _saleCommand ?? (_saleCommand = new RelayCommand((param) => this.Sale())); }
        }

        private void Sale()
        {
            SaleViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is SaleViewModel)
                {
                    workspace = vm as SaleViewModel;
                }
            }

            if (workspace == null)
            {
                workspace = new SaleViewModel(_companyInfoRepository.GetCompanyInfos()[0]);
                workspace.StaffUNK = this.CurrentStaff.StaffUNK;
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _manageInvoiceTemplateCommand;
        public ICommand ManageInvoiceTemplateCommand
        {
            get { return _manageInvoiceTemplateCommand ?? (_manageInvoiceTemplateCommand = new RelayCommand((param) => this.ManageInvoiceTemplate())); }
        }

        private void ManageInvoiceTemplate()
        {
            InvoiceTemplateViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is InvoiceTemplateViewModel)
                {
                    workspace = vm as InvoiceTemplateViewModel;
                }
            }

            if (workspace == null)
            {
                workspace = new InvoiceTemplateViewModel();
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _accReceivableCommand;
        public ICommand AccountReceivableCommand
        {
            get { return _accReceivableCommand ?? (_accReceivableCommand = new RelayCommand((param) => this.AccountReceivable())); }
        }

        private void AccountReceivable()
        {
            AccReceivableViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is AccReceivableViewModel)
                {
                    workspace = vm as AccReceivableViewModel;
                }
            }

            if (workspace == null)
            {
                workspace = new AccReceivableViewModel(_companyInfoRepository.CompanyInformation);
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _accPayableCommand;
        public ICommand AccountPayableCommand
        {
            get { return _accPayableCommand ?? (_accPayableCommand = new RelayCommand((param) => this.AccountPayable())); }
        }

        private void AccountPayable()
        {
            AccPayableViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is AccPayableViewModel)
                {
                    workspace = vm as AccPayableViewModel;
                }
            }

            if (workspace == null)
            {
                workspace = new AccPayableViewModel(_companyInfoRepository.CompanyInformation);
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _editProfileCommand;
        public ICommand EditProfileCommand
        {
            get { return _editProfileCommand ?? (_editProfileCommand = new RelayCommand((param) => this.EditProfile())); }
        }

        private void EditProfile()
        {
            EditProfileViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is EditProfileViewModel)
                {
                    workspace = vm as EditProfileViewModel;
                }
            }

            if (workspace == null)
            {
                workspace = new EditProfileViewModel(this.CurrentStaff.CreateShallowCopy());
                workspace.RequestClose += new EventHandler(workspaceEditProfile_RequestClose);
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        void workspaceEditProfile_RequestClose(object sender, EventArgs e)
        {
            this.CurrentStaff = ((EditProfileViewModel)sender).CurrentStaff;
        }

        private RelayCommand _manageAccountCommand;
        public ICommand ManageAccountCommand
        {
            get { return _manageAccountCommand ?? (_manageAccountCommand = new RelayCommand((param) => this.ManageAccount())); }
        }

        private void ManageAccount()
        {
            AccountViewModel workspace = null;
            foreach (WorkspaceViewModel vm in this.Workspaces)
            {
                if (vm is AccountViewModel)
                {
                    workspace = vm as AccountViewModel;
                }
            }

            if (workspace == null)
            {
                workspace = new AccountViewModel();
                this.Workspaces.Add(workspace);
            }

            this.SetActiveWorkspace(workspace);
        }

        private RelayCommand _closeWorkspacesCommand;
        public ICommand CloseWorkspacesCommand
        {
            get { return _closeWorkspacesCommand ?? (_closeWorkspacesCommand = new RelayCommand((param) => this.CloseWorkspaces())); }
        }

        private void CloseWorkspaces()
        {
            while (Workspaces.Count > 0)
            {
                Workspaces.RemoveAt(Workspaces.Count - 1);
            }
        }
        #endregion

        #region Public Members

        ObservableCollection<WorkspaceViewModel> _workspaces;

        /// <summary>
        /// Returns the collection of available workspaces to display.
        /// A 'workspace' is a ViewModel that can request to be closed.
        /// </summary>
        public ObservableCollection<WorkspaceViewModel> Workspaces
        {
            get
            {
                if (_workspaces == null)
                {
                    _workspaces = new ObservableCollection<WorkspaceViewModel>();
                    _workspaces.CollectionChanged += this.Workspaces_CollectionChanged;
                }
                return _workspaces;
            }
        }

        public bool IsSaleManager { get { return this.CurrentStaff.SType == StaffTypes.SaleManager; } }
        public bool IsStoreManager { get { return this.CurrentStaff.SType == StaffTypes.StoreManager; } }
        public bool IsInvoiceManager { get { return this.CurrentStaff.SType == StaffTypes.InvoiceManager; } }
        public bool IsSaleWorker { get { return this.CurrentStaff.SType == StaffTypes.SaleWorker; } }
        public bool IsAccountant { get { return this.CurrentStaff.SType == StaffTypes.Accountant; } }
        public bool IsCashier { get { return this.CurrentStaff.SType == StaffTypes.Cashier; } }       
        public bool IsAdmin { get { { return this.CurrentStaff.SType == StaffTypes.Admin; } } }

        public string CurrentStaffInformation { get { return this.CurrentStaff.Username; } }

        /// <summary>
        /// Thong tin cua user hien tai. CHU Y NEN DUNG
        /// </summary>
        public Staff CurrentStaff { get; set; }

        public string ManageStaffsDesc { get { return Resources.MainWin_ManageStaffs_Desc; } }
        public string ManageCustomersDesc { get { return Resources.MainWin_ManageCustomers_Desc; } }
        public string ManageSuppliersDesc { get { return Resources.MainWin_ManageSuppliers_Desc; } }
        public string ManageProductsDesc { get { return Resources.MainWin_ManageProducts_Desc; } }
        public string ManageCategoriesDesc { get { return Resources.MainWin_ManageCategories_Desc; } }
        public string ReceiveGoodsDesc { get { return Resources.MainWin_ReceiveGoods_Desc; } }
        public string SaleDesc { get { return Resources.MainWin_Sales_Desc; } }
        public string ManageAccountsDesc { get { return Resources.MainWin_ManageAccounts_Desc; } }
        public string ManageInvoiceTemplatesDesc { get { return Resources.MainWin_InvTemplates_Desc; } }
        public string RegisterDesc { get { return Resources.MainWin_RegisterInvPrinting_Desc; } }
        public string AccReceivableDesc { get { return Resources.MainWin_Receivable_Desc; } }
        public string AccPayableDesc { get { return Resources.MainWin_Payable_Desc; } }
        public string ManageCompanyInfoDesc { get { return Resources.MainWin_CompanyInfo_Desc; } }
        #endregion

        #region Private helpers
        void SetActiveWorkspace(WorkspaceViewModel workspace)
        {
            Debug.Assert(this.Workspaces.Contains(workspace));

            ICollectionView collectionView = CollectionViewSource.GetDefaultView(this.Workspaces);
            if (collectionView != null)
                collectionView.MoveCurrentTo(workspace);
        }
        #endregion
    }
}


